#ifndef GEO2D_H
#define GEO2D_H

#include <utility>
#include <vector>

#include "base.h"

namespace geo2d {
    struct Point2d {
        double x, y;
        Point2d() {}
        Point2d(double x, double y) : x(x), y(y) {}

        // 重载运算符：向量加法
        Point2d operator+(const Point2d& p) const {
            return Point2d(x + p.x, y + p.y);
        }

        // 重载运算符：向量减法
        Point2d operator-(const Point2d& p) const {
            return Point2d(x - p.x, y - p.y);
        }

        Point2d& operator+=(const Point2d& p) {
            x += p.x;
            y += p.y;
            return *this;
        }

        Point2d& operator-=(const Point2d& p) {
            x -= p.x;
            y -= p.y;
            return *this;
        }

        // 重载运算符：向量与标量乘法
        Point2d operator*(double d) const {
            return Point2d(x * d, y * d);
        }

        Point2d operator/(double d) const {
            return Point2d(x / d, y / d);
        }
    };
    
    double crossProduct(Point2d a, Point2d b);
    double crossProduct(const Point2d &a, const Point2d &b, const Point2d &c);
    bool onSegment(const Point2d &p, const Point2d &q, const Point2d &r);
    int orientation(const Point2d &p, const Point2d &q, const Point2d &r);
    bool segmentsIntersect(const Point2d &p1, const Point2d &p2,
                           const Point2d &p3, const Point2d &p4);
    bool lineIntersection(const Point2d &A, const Point2d &B,
                          const Point2d &C, const Point2d &D,
                          Point2d &intersect);                       
    void getTriangleCircumcenter(Point2d a, Point2d b, Point2d c, Point2d& center, double& radius);
    // other 是否在以 p1, p2 为直径的圆内
    bool InCircle(Point2d p1, Point2d p2, Point2d other);
    // 计算三角形面积
    double triangleArea(Point2d a, Point2d b, Point2d c);
    // 点 p 是否在三角形内
    bool isPointInsideTriangle(Point2d a, Point2d b, Point2d c, Point2d p);

    std::pair<bool, int> checkQuadrilateralConvexity(const Point2d &p1, const Point2d &p2,
                                                    const Point2d &p3, const Point2d &p4);
    
    void searchPointOnSurface(const std::vector<Point2d> &points, const std::vector<int> &is_convex, const Point2d &p, int &x, int &y, int nx, int ny);
}; // namespace geo2d

#endif // GEO2D_H
